/*
 * @Author: zxc
 * @Date: 2020-11-12 10:17:54
 * @LastEditTime: 2020-11-12 14:06:05
 * @LastEditors: zxc
 * @Description: 发布-订阅模式 又称 观察者模式
 */
// let salesOffices = {}
// // salesOffices.clientList []
// salesOffices.clientList = {}

// // salesOffices.listen = function (fn) {
// //   this.clientList.push(fn)
// // }

// salesOffices.listen = function (key, fn) {
//   if (!this.clientList[key]) {
//     this.clientList[key] = []
//   }
//   this.clientList[key].push(fn)
// }

// // salesOffices.trigger = function (...args) {
// //   for (var i = 0, fn; (fn = this.clientList[i++]); ) {
// //     fn.apply(this, args)
// //   }
// // }

// salesOffices.trigger = function (...args) {
//   let key = args.shift(),
//     fns = this.clientList[key]
//   if (!fns || fns.length === 0) {
//     return false
//   }
//   for (var i = 0, fn; (fn = fns[i++]); ) {
//     fn.apply(this, args)
//   }
// }

// // salesOffices.listen(function (price, squareMeter) {
// //   console.log("价格-" + price)
// //   console.log("squareMeter=" + squareMeter)
// // })

// // salesOffices.listen(function (price, squareMeter) {
// //   console.log("价格-" + price)
// //   console.log("squareMeter=" + squareMeter)
// // })

// // salesOffices.trigger(200, 88)
// // salesOffices.trigger(230, 95)

// salesOffices.listen("sq88", function (price) {
//   console.log("小明，你好，88平的现在价格-" + price)
// })
// salesOffices.listen("sq98", function (price) {
//   console.log("小芳，你好，98平的现在价格-" + price)
// })
// salesOffices.trigger("sq88", 2000000)
// salesOffices.trigger("sq98", 2400000)

// 简单封装
// const events = {
//   clientList: {},
//   listen(key, fn) {
//     if (!this.clientList[key]) {
//       this.clientList[key] = []
//     }
//     this.clientList[key].push(fn)
//   },
//   trigger(...args) {
//     let key = args.shift(),
//       fns = this.clientList[key]
//     if (!fns || fns.length === 0) {
//       return false
//     }
//     for (var i = 0, fn; (fn = fns[i++]); ) {
//       fn.apply(this, args)
//     }
//   },
//   remove(key, fn) {
//     let fns = this.clientList[key]
//     if (!fns) return false
//     if (!fn) {
//       fns && (fns.length = 0)
//     } else {
//       for (var i = fns.length - 1; i > 0; i--) {
//         let _fn = fns[i]
//         if (_fn === fn) {
//           fns.splice(i, 1)
//         }
//       }
//     }
//   }
// }

// let installEvent = function (obj) {
//   for (var i in events) {
//     obj[i] = events[i]
//   }
// }

// let salesOffices = {}
// installEvent(salesOffices)
// salesOffices.listen(
//   "sq88",
//   (fn1 = function (price) {
//     console.log("小明，你好，88平的现在价格-" + price)
//   })
// )
// salesOffices.listen("sq98", function (price) {
//   console.log("小芳，你好，98平的现在价格-" + price)
// })
// salesOffices.remove("sq88", fn1)
// salesOffices.trigger("sq98", 2400000)

//登陆
// login.succ(function(data){
//   header.setAvatar(data.avatar)
//   nav.setAvatar(data.avatar)
//   message.refresh()
//   cart.refresh()
// })()

// const login = {
//   clientList: {},
//   listen(key, fn) {
//     if (!this.clientList[key]) {
//       this.clientList[key] = []
//     }
//     this.clientList[key].push(fn)
//   },
//   trigger(...args) {
//     let key = args.shift(),
//       fns = this.clientList[key]
//     if (!fns || fns.length === 0) {
//       return false
//     }
//     for (var i = 0, fn; (fn = fns[i++]); ) {
//       fn.apply(this, args)
//     }
//   }
// }
// function loginin() {
//   return Promise.resolve({ avatar: "kk" })
// }
// loginin().then(res => {
//   login.trigger("loginSucc", res)
// })
// let header = (function () {
//   login.listen("loginSucc", function (data) {
//     header.setAvatar(data.avatar)
//   })
//   return {
//     setAvatar(data) {
//       console.log("设置header模块的头象")
//     }
//   }
// })()
// let nav = (function () {
//   login.listen("loginSucc", function (data) {
//     nav.setAvatar(data.avatar)
//   })
//   return {
//     setAvatar(data) {
//       console.log("设置nav模块的头象")
//     }
//   }
// })()

// 全局订阅
// let Events = (function () {
//   let clientList = {}
//   let listen, trigger, remove
//   listen = function (key, fn) {
//     if (!clientList[key]) {
//       clientList[key] = []
//     }
//     clientList[key].push(fn)
//   }
//   trigger = function (...args) {
//     let key = args.shift(),
//       fns = clientList[key]
//     if (!fns || fns.length === 0) {
//       return false
//     }
//     for (var i = 0, fn; (fn = fns[i++]); ) {
//       fn.apply(this, args)
//     }
//   }

//   remove = function (key, fn) {
//     let fns = clientList[key]
//     if (!fns) return false
//     if (!fn) {
//       fns && (fns.length = 0)
//     } else {
//       for (var i = fns.length - 1; i > 0; i--) {
//         let _fn = fns[i]
//         if (_fn === fn) {
//           fns.splice(i, 1)
//         }
//       }
//     }
//   }
//   return {
//     listen,
//     trigger,
//     remove
//   }
// })()

// Events.listen("sq88", function (price) {
//   console.log("price-" + price)
// })
// Events.trigger("sq88", 2000000)

//全局命名冲突解决 => 命名空间
let Events = (function () {
  let global = this,
    Events,
    _default = "default"
  Events = (function () {
    let _listen,
      _trigger,
      _remove,
      _shift = Array.prototype.shift,
      _unshift = Array.prototype.unshift,
      namespaceCache = {},
      _create,
      each = function (ary, fn) {
        let ret
        for (let i = 0, l = ary.length; i < l; i++) {
          let n = ary[i]
          ret = fn.call(n, i, n)
        }
        return ret
      }
    _listen = function (key, fn, cache) {
      if (!cache[key]) {
        cache[key] = []
      }
      cache[key].push(fn)
    }
    _remove = function (key, cache, fn) {
      if (cache[key]) {
        if (fn) {
          for (let i = cache[key].length; i >= 0; i--) {
            if (cache[key] === fn) {
              cache[key].splice(i, 1)
            }
          }
        } else {
          cache[key] = []
        }
      }
    }
    _trigger = function (...arg) {
      let cache = arg.shift(),
        key = arg.shift(),
        args = arg,
        _self = this,
        ret,
        stack = cache[key]
      if (!stack || !stack.length) {
        return
      }
      return each(stack, function () {
        return this.apply(_self, args)
      })
    }
    _create = function (namespace = _default) {
      let cache = {},
        offlineStack = [], // 离线事件
        ret = {
          listen: function (key, fn, last) {
            _listen(key, fn, cache)
            if (offlineStack === null) {
              return
            }
            if (last === "last") {
              offlineStack.length && offlineStack.pop()()
            } else {
              each(offlineStack, function () {
                this()
              })
            }
            offlineStack = null
          },
          one: function (key, fn, last) {
            _remove(key, cache)
            this.listen(key, fn, last)
          },
          remove: function (key, fn) {
            _remove(key, cache, fn)
          },
          trigger: function () {
            let fn,
              args,
              _self = this
            _unshift.call(arguments, cache)
            args = arguments
            fn = function () {
              return _trigger.apply(_self, args)
            }
            if (offlineStack) {
              return offlineStack.push(fn)
            }
            return fn()
          }
        }
      return namespace
        ? namespaceCache[namespace]
          ? namespaceCache[namespace]
          : (namespaceCache[namespace] = ret)
        : ret
    }
    return {
      create: _create,
      one: function (key, fn, last) {
        let event = this.create()
        event.one(key, fn, last)
      },
      remove: function (key, fn) {
        let event = this.create()
        event.remove(key, fn)
      },
      listen: function (key, fn, last) {
        let event = this.create()
        event.listen(key, fn, last)
      },
      trigger: function () {
        let event = this.create()
        event.trigger.apply(this, arguments)
      }
    }
  })()
  return Events
})()

// Events.trigger("click", 1)
// Events.listen("click", function (a) {
//   console.log(a)
// })

Events.create("namespace1").listen("click", function (a) {
  console.log(a)
})
Events.create("namespace1").trigger("click", 1)

Events.create("namespace2").listen("click", function (a) {
  console.log(a)
})
Events.create("namespace2").trigger("click", 2)
